package com.party.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.party.common.base.ApiResult;
import com.party.common.entity.MyPage;
import com.party.common.utils.PageUtil;
import com.party.entity.*;
import com.party.entity.dto.QueryResourceDto;
import com.party.entity.dto.QueryStationDto;
import com.party.mapper.PbResourceMapper;
import com.party.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.party.util.DateUtils;
import com.party.util.MoJiCommonUtils;
import lombok.extern.slf4j.Slf4j;
import nl.siegmann.epublib.domain.Book;
import nl.siegmann.epublib.epub.EpubReader;
import org.springframework.beans.BeanUtils;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 资源 服务实现类
 * </p>
 *
 * @author ccl
 * @since 2024-10-25
 */
@Slf4j
@Service
public class PbResourceServiceImpl extends ServiceImpl<PbResourceMapper, PbResource> implements PbResourceService {

    @Resource
    private PbUserService pbUserService;

    @Resource
    private PbUserResourceService pbUserResourceService;

    @Resource
    private PbResourceDeviceService pbResourceDeviceService;

    @Resource
    private PbUserResourceHistoryService pbUserResourceHistoryService;

    @Override
    public boolean add(PbResource pbResource) {
        PbResource pbResource1=this.getOne(new LambdaQueryWrapper<PbResource>()
                .eq(PbResource::getResourceName,pbResource.getResourceName()));
        if(pbResource1 !=null){
            throw new RuntimeException("资源名称已存在,请核查!");
        }
        pbResource1.setCreateTime(new Date());
        return this.save(pbResource1);
    }

    @Override
    public boolean edit(PbResource pbResource) {
        PbResource pbResource1=this.getById(pbResource.getResourceId());
        if(!pbResource1.getResourceName().equals(pbResource.getResourceName())){
            PbResource pbDevice2=this.getOne(new LambdaQueryWrapper<PbResource>()
                    .eq(PbResource::getResourceName,pbResource.getResourceName()));
            if(pbDevice2 !=null){
                throw new RuntimeException("资源名称已存在,请核查!");
            }
        }
        return this.updateById(pbResource);
    }

    @Override
    public boolean delete(Long id) {
        return this.removeById(id);
    }

    @Override
    public MyPage<PbResource> queryPage(QueryResourceDto dto) {
        LambdaQueryWrapper<PbResource> wrapper = new LambdaQueryWrapper<>();
        if (ObjectUtil.isNotEmpty(dto.getResourceName())) {
            wrapper.like(PbResource::getResourceName, dto.getResourceName());
        }
        if (ObjectUtil.isNotEmpty(dto.getDataTypeId())) {
            wrapper.eq(PbResource::getDataTypeId, dto.getDataTypeId());
        }

        //管理员查看全部,非管理员查看各自的
        String loginId=MoJiCommonUtils.getLoginId();
        if(!"admin".equals(loginId)){
            PbUser pbUser=pbUserService.getOne(new LambdaQueryWrapper<PbUser>()
            .eq(PbUser::getUserCode,MoJiCommonUtils.getUserCode()));
            if(pbUser !=null){
                List<PbUserResource> pbUserResources=pbUserResourceService.list(
                        new LambdaQueryWrapper<PbUserResource>()
                        .eq(PbUserResource::getUserId,pbUser.getId()));
                if(ObjectUtil.isEmpty(pbUserResources)){
                    wrapper.eq(PbResource::getResourceId, 0);
                }else {
                    List<Long> idList = pbUserResources.stream().map(PbUserResource::getResourceId).collect(Collectors.toList());
                    if (ObjectUtil.isNotEmpty(idList)) {
                        wrapper.in(PbResource::getResourceId, idList);
                    }
                }
            }
        }
        //wrapper.eq(PbResource::getStatus, 1);
        PageHelper.startPage(dto.getPageNum(), dto.getPageSize());
        wrapper.orderByDesc(PbResource::getCreateTime);
        List<PbResource> pbResourceList = this.list(wrapper);
        if(ObjectUtil.isNotEmpty(pbResourceList) && ObjectUtil.isNotEmpty(dto.getDeviceId()) ){
            pbResourceList.forEach(pbResource -> {
                PbResourceDevice pbResourceDevice=pbResourceDeviceService.getOne(new LambdaQueryWrapper<PbResourceDevice>()
                .eq(PbResourceDevice::getDeviceId,Long.parseLong(dto.getDeviceId()))
                .eq(PbResourceDevice::getResourceId,pbResource.getResourceId()));
                if(pbResourceDevice !=null){
                    if(pbResourceDevice.getSfRecommend() ==null){
                        pbResource.setSfRecommend(0);
                    }else{
                        pbResource.setSfRecommend(pbResourceDevice.getSfRecommend());
                    }
                }else{
                    pbResource.setSfRecommend(0);
                }
            });
        }
        PageInfo<PbResource> info = new PageInfo<>(pbResourceList);
        return PageUtil.PageInfo2MyPage(info);
    }

    @Override
    public PbResource detail(Long id) {
        return this.getById(id);
    }

    @Override
    public ApiResult synchronous() {
        try {
            String token = selectToken("http://10.100.24.103:9999" + "/auth/oauth2/token");
            ObjectMapper objectMapper = new ObjectMapper();
            BookExposureEntity bookExposureEntity = new BookExposureEntity();
            bookExposureEntity.setUsername("hndzyx");
            bookExposureEntity.setPassword("123456");
            bookExposureEntity.setFromSys("1");
            bookExposureEntity.setProductId("1850710022997258241");
            String json = objectMapper.writeValueAsString(bookExposureEntity);
            String jsonString = resourceType(token, "http://10.100.24.103:9999" + "/digitallibrary/bookExposure/getProductResources", json);
            JSONObject jsonObject = JSON.parseObject(jsonString);
            JSONArray dataArray = jsonObject.getJSONArray("data");
            LambdaQueryWrapper<PbResource> wrapper = Wrappers.lambdaQuery();
            this.remove(wrapper);
            for (int i = 0; i < dataArray.size(); i++) {
                JSONObject dataObject = dataArray.getJSONObject(i);
                PbResource pbResource = new PbResource();
                String id = dataObject.getString("resourceId");
                pbResource.setResourceId(Long.valueOf(id));
                pbResource.setResourceName(dataObject.getString("resourceName"));
                if(ObjectUtil.isNotEmpty(dataObject.getString("bookTypeId"))){
                    pbResource.setBookTypeId(Long.parseLong(dataObject.getString("bookTypeId")));
                }
                pbResource.setAuthor(dataObject.getString("author"));
                pbResource.setCover(dataObject.getString("coverPictureUrl"));
                if(ObjectUtil.isNotEmpty(dataObject.getString("dataTypeId"))){
                    pbResource.setDataTypeId(Long.parseLong(dataObject.getString("dataTypeId")));
                }
                if(dataObject.getString("createTime")!=null)
                {
                    if(DateUtils.getDate(dataObject.getString("createTime"),DateUtils.DATETIME_PATTERN)!=null)
                    {
                        pbResource.setCreateTime(DateUtils.getDate(dataObject.getString("createTime"),DateUtils.DATETIME_PATTERN));
                    }
                }

                pbResource.setBriefIntroduction(dataObject.getString("briefIntroduction"));
                pbResource.setPress(dataObject.getString("press"));
                pbResource.setStatus("1");
                this.save(pbResource);
            }
            return ApiResult.ok("同步成功");
        } catch (Exception e) {
            return ApiResult.failed("同步失败");
        }
    }

    @Override
    public boolean like(Long id, Integer likeCount) {
        PbResource pbResource=this.getById(id);
        if(pbResource==null){
            throw new RuntimeException("资源不存在,请核查!");
        }
        pbResource.setLikeCount(likeCount);
        return this.updateById(pbResource);
    }

    @Override
    public JSONObject detailWx(Long id,String openId) {
        try {
            PbResource byId = this.getById(id);
            if(byId==null){
                throw new RuntimeException("资源不存在,请核查!");
            }
            String token = selectToken("http://10.100.24.103:9999" + "/auth/oauth2/token");
            ObjectMapper objectMapper = new ObjectMapper();
            BookExposureEntity bookExposureEntity = new BookExposureEntity();
            bookExposureEntity.setUsername("hndzyx");
            bookExposureEntity.setPassword("123456");
            bookExposureEntity.setFromSys("1");
            bookExposureEntity.setProductId("1850710022997258241");
            bookExposureEntity.setResourceId(byId.getResourceId()+"");
            String json = objectMapper.writeValueAsString(bookExposureEntity);
            String jsonString =
                    //"{\"code\":0,\"msg\":\"汉魏士人的思想历程详情\",\"data\":{\"id\":\"1724497002389471233\",\"bookName\":\"汉魏士人的思想历程\",\"author\":\"孙生 白笑天\",\"bookNumber\":\"978-7-227-04912-8\",\"briefIntroduction\":null,\"press\":\"宁夏人民出版社\",\"publicationTime\":\"2011-12-01\",\"bookClassification\":\"社会科学总论\",\"dataTypeId\":\"1719628518976913409\",\"bookDataType\":\"电子书\",\"bookGradeType\":\"B\",\"labelType\":null,\"copyrightOwner\":\"北京九州文心\",\"file\":[{\"fileName\":\"汉魏士人的思想历程\",\"size\":3.0,\"resourceName\":\"汉魏士人的思想历程\",\"fileUrl\":\"https://zhongtai.zhongjiaoyuntu.com:9002/dzyx/20240428/黄老师上传1宁夏吉林/汉魏士人的思想历程/汉魏士人的思想历程.pdf\",\"type\":\"pdf\"}],\"coverPictures\":[{\"coverPictureName\":\"汉魏士人的思想历程\",\"coverPictureUrl\":\"https://zhongtai.zhongjiaoyuntu.com:9002/dzyx/20240428/黄老师上传1宁夏吉林/汉魏士人的思想历程/汉魏士人的思想历程.jpg\",\"type\":\"jpg\"}]}}\n";
                    resourceType(token, "http://10.100.24.103:9999" + "/digitallibrary/bookExposure/getProductResourcesDetails", json);
            log.info("资源返回报文=============={}",jsonString);

            JSONObject jsonObject = JSON.parseObject(jsonString);
            Long pageView = byId.getPageView();
            byId.setPageView(pageView + 1);
            this.updateById(byId);
            jsonObject.put("pageView", byId.getPageView());
            System.out.println(jsonObject);
            LambdaQueryWrapper<PbUserResourceHistory> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(PbUserResourceHistory::getOpenId,openId);
            wrapper.eq(PbUserResourceHistory::getResourceId,id);
//            List<PbUserResourceHistory> list = pbUserResourceHistoryService.list(wrapper);
//            PbUserResourceHistory pbUserResourceHistoryOld=pbUserResourceHistoryService.getById(id);
            if(  pbUserResourceHistoryService.list(wrapper).size()==0||pbUserResourceHistoryService.list(wrapper)==null){
                PbUserResourceHistory pbUserResourceHistory=new PbUserResourceHistory();
                pbUserResourceHistory.setOpenId(openId);
                BeanUtils.copyProperties(byId,pbUserResourceHistory);
                pbUserResourceHistory.setCreateTime(new Date());
                pbUserResourceHistory.setResourceId(id);
                pbUserResourceHistoryService.save(pbUserResourceHistory);
            }

            return jsonObject;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public String downloadAndParseEpub(String epubUrl) {
        //String s = "http://10.100.24.103:9000/lengleng/" + epubUrl;
        epubUrl = "http://10.100.24.103:9000"+epubUrl.replace("https://zhongtai.zhongjiaoyuntu.com:9002","");
        try {
            URL url = new URL(epubUrl);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            InputStream inputStream;

            if (connection.getResponseCode() >= 400) {
                inputStream = connection.getErrorStream();
            } else {
                inputStream = connection.getInputStream();
            }

            try (BufferedInputStream in = new BufferedInputStream(inputStream)) {
                // 解析EPUB文件
                Book book = (new EpubReader()).readEpub(in);

                // 获取HTML内容
                StringBuilder htmlContent = new StringBuilder();
                int i = 1;
                for (nl.siegmann.epublib.domain.Resource resource : book.getContents()) {
                    String content = new String(resource.getData());
                    content = saveImages(content, i);
                    htmlContent.append(content);
                    i++;
                }

                return htmlContent.toString();
            }
        } catch (IOException e) {
            log.info("epub异常:{}",e);
            e.printStackTrace();
            return "处理EPUB文件时发生错误。";
        }
    }

    @Override
    public boolean upAndDown(Long id) {
        PbResource pbResource=this.getById(id);
        if(pbResource==null){
            throw new RuntimeException("资源不存在,请核查!");
        }
        if(pbResource.getStatus().equals("0")){
            pbResource.setStatus("1");
        }
        if(pbResource.getStatus().equals("1")){
            pbResource.setStatus("0");
        }
        return this.updateById(pbResource);
    }

    @Override
    public MyPage<PbResource> queryAppPage(QueryResourceDto dto) {
        LambdaQueryWrapper<PbResource> wrapper = new LambdaQueryWrapper<>();
        if (ObjectUtil.isNotEmpty(dto.getResourceName())) {
            wrapper.like(PbResource::getResourceName, dto.getResourceName());
        }
        //管理员查看全部,非管理员查看各自的
        String loginId=MoJiCommonUtils.getLoginId();
        if(!"admin".equals(loginId)){
            PbUser pbUser=pbUserService.getOne(new LambdaQueryWrapper<PbUser>()
                    .eq(PbUser::getUserCode,MoJiCommonUtils.getUserCode()));
            if(pbUser !=null){
                List<PbUserResource> pbUserResources=pbUserResourceService.list(
                        new LambdaQueryWrapper<PbUserResource>()
                                .eq(PbUserResource::getUserId,pbUser.getId()));
                if(ObjectUtil.isEmpty(pbUserResources)){
                    wrapper.eq(PbResource::getResourceId, 0);
                }else {
                    List<Long> idList = pbUserResources.stream().map(PbUserResource::getResourceId).collect(Collectors.toList());
                    if (ObjectUtil.isNotEmpty(idList)) {
                        wrapper.in(PbResource::getResourceId, idList);
                    }
                }
            }
        }
        wrapper.eq(PbResource::getStatus, 1);
        PageHelper.startPage(dto.getPageNum(), dto.getPageSize());
        wrapper.orderByDesc(PbResource::getCreateTime);
        List<PbResource> pbResourceList = this.list(wrapper);
        PageInfo<PbResource> info = new PageInfo<>(pbResourceList);
        return PageUtil.PageInfo2MyPage(info);
    }

    @Override
    public boolean recommend(String deviceId,String resourceId) {
        if(ObjectUtil.isEmpty(deviceId)){
            throw new RuntimeException("设备ID不能为空,请核查!");
        }
        PbResource pbResource=this.getOne(new LambdaQueryWrapper<PbResource>()
                .eq(PbResource::getResourceId,Long.valueOf(resourceId)));
        if(pbResource==null){
            throw new RuntimeException("资源不存在,请核查!");
        }
        LambdaQueryWrapper<PbResourceDevice> wrapper=new LambdaQueryWrapper<>();
        wrapper.eq(PbResourceDevice::getDeviceId,Long.valueOf(deviceId));
        wrapper.eq(PbResourceDevice::getResourceId,Long.valueOf(resourceId));
        PbResourceDevice pbResourceDevice=pbResourceDeviceService.getOne(wrapper);
        if(pbResourceDevice==null){
            throw new RuntimeException("资源还未绑定设备,请先绑定设备再推荐!");
        }
        if(pbResourceDevice.getSfRecommend() ==null){
            pbResourceDevice.setSfRecommend(1);
        }else if(pbResourceDevice.getSfRecommend()==1){
            pbResourceDevice.setSfRecommend(0);
        }else{
            pbResourceDevice.setSfRecommend(1);
        }
        pbResourceDeviceService.updateById(pbResourceDevice);
        return this.updateById(pbResource);
    }

    @Override
    public List<PbResource> hotRecommend() {
        LambdaQueryWrapper<PbResource> wrapper1 = new LambdaQueryWrapper<>();
        wrapper1.orderByDesc(PbResource::getCreateTime);
        wrapper1.last("limit 9");
        List<PbResource> resourceList=this.list(wrapper1);
        return resourceList;
    }

    private String saveImages(String content, int chapterNumber) {
        int i = 0;
        while (content.contains("data:image/png;base64,")) {
            int startIndex = content.indexOf("data:image/png;base64,");
            int endIndex = content.indexOf("\"", startIndex);
            String base64Data = content.substring(startIndex + 22, endIndex);

            // Save image to file
            String fileName = "chapter_" + chapterNumber + "_image_" + i + ".png";
            saveImageToFile(base64Data, fileName);

            // Replace Base64 data with file path
            content = content.replace("data:image/png;base64," + base64Data, fileName);
            i++;
        }

        return content;
    }
    private void saveImageToFile(String base64Data, String fileName) {
        try {
            byte[] imageBytes = Base64.getDecoder().decode(base64Data);
            try (FileOutputStream imageOutputStream = new FileOutputStream(fileName)) {
                imageOutputStream.write(imageBytes);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 同步数据工具类
     * @param pathUrl
     * @return
     */
    public static String selectToken(String pathUrl) {
//        String result = "{\"sub\":\"jkuser\",\"iss\":\"https://pig4cloud.com\",\"active\":true,\"token_type\":\"Bearer\",\"client_id\":\"test\",\"access_token\":\"3fa904a3-ff7b-4395-ba99-db56b1ffcb7a\",\"refresh_token\":\"GJqqAteG0QhPUx5KYO031DlpklnxO4Wlhw07BNQhsagJ6DYAqjfei2eZXJ9PrZGL74mjmA3HpAEWvC7EJIhPDsFhWKMlvKQ-8rqgdIS-uGM-8gGIRb8G9AgRlPBkzSMr\",\"aud\":[\"test\"],\"license\":\"https://pig4cloud.com\",\"nbf\":1729661681.737000000,\"user_id\":1738111795169611778,\"scope\":[\"server\"],\"exp\":1729704881.737000000,\"expires_in\":43200,\"iat\":1729661681.737000000,\"jti\":\"364d9be6-7c36-4c8a-a23d-afb4a229c762\",\"username\":\"jkuser\"}\n";
        String result ="";
        String data = "";
        String username = "jkuser";
        String password = "JFat0Zdc";
        String scope = "server";

        try {
            URL url = new URL(pathUrl);

            //打开和url之间的连接
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();

            //设定请求的方法为"POST"，默认是GET
            //post与get的不同之处在于post的参数不是放在URL字串里面，而是放在http请求的正文内。
            conn.setRequestMethod("POST");

            //设置30秒连接超时
            conn.setConnectTimeout(30000);
            //设置30秒读取超时
            conn.setReadTimeout(30000);

            // 设置是否向httpUrlConnection输出，因为这个是post请求，参数要放在http正文内，因此需要设为true, 默认情况下是false;
            conn.setDoOutput(true);
            // 设置是否从httpUrlConnection读入，默认情况下是true;
            conn.setDoInput(true);

            // Post请求不能使用缓存
            conn.setUseCaches(false);

            //设置通用的请求属性
            conn.setRequestProperty("skipToken", "true");
            conn.setRequestProperty("Accept-Charset", "utf-8");
            conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
            // 添加基本身份验证
            conn.setRequestProperty("Authorization", "Basic dGVzdDp0ZXN0");

            String encodedParams = "username=" + URLEncoder.encode(username, String.valueOf(StandardCharsets.UTF_8)) +
                    "&password=" + URLEncoder.encode(password, String.valueOf(StandardCharsets.UTF_8)) +
                    "&scope=" + URLEncoder.encode(scope, String.valueOf(StandardCharsets.UTF_8)) +
                    "&grant_type=" + URLEncoder.encode("password", String.valueOf(StandardCharsets.UTF_8));

            conn.getOutputStream().write(encodedParams.getBytes());

            //连接，从上述url.openConnection()至此的配置必须要在connect之前完成，
            int code = conn.getResponseCode();//获得响应码
            log.info("token接口响应码1=============={}",code);
            if (code == 200) {//响应成功，获得响应的数据

                //解决中文乱码
                BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
                log.info("token接口响应码2=============={}",reader);
                //解决返回参数换行问题，一次读一行，读入null时文件结束
                int line = 1;
                String tempString = null;
                while ((tempString = reader.readLine()) != null) {
                    result += tempString;
                    //把当前行号显示出来
                    //System.out.println("line " + line + ": " + tempString);
                    line++;
                }
                log.info("token接口响应码3=============={}",result);
                reader.close();

            }
            conn.disconnect();   //断开连接


            ObjectMapper objectMapper = new ObjectMapper();

            JsonNode rootNode = objectMapper.readTree(result);
            log.info("token接口响应码4=============={}",rootNode);
            String tokenType = rootNode.get("token_type").asText();
            String accessToken = rootNode.get("access_token").asText();
            log.info("JsonNode:" + rootNode);
            data = tokenType + ' ' + accessToken;

        } catch (Exception e) {
            e.printStackTrace();
        }

        return data;
    }
    public static String resourceType(String Authorization, String httpUrl, String requestData) {
        String responseData = "";
        try {
            URL url = new URL(httpUrl);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();

            connection.setRequestProperty("Content-Type", "application/json; charset=utf-8");
            if (Authorization != null){
                connection.setRequestProperty("Authorization", Authorization);
            }


            connection.setDoOutput(true);
            connection.setDoInput(true);
            connection.setRequestMethod("POST");

            OutputStream outputStream = connection.getOutputStream();
            outputStream.write(requestData.getBytes("UTF-8"));

            outputStream.flush();
            outputStream.close();

            int responseCode = connection.getResponseCode();
            if (responseCode == 200) { // 响应成功，获取响应数据

                BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));

                String tempString;
                while ((tempString = reader.readLine()) != null) {
                    responseData += tempString;
                }
                reader.close();
            }

            connection.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return responseData;
    }
    public static String get(String Authorization, String httpUrl) {
        String responseData = "";
        try {

            URL url = new URL(httpUrl);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();

            connection.setRequestProperty("Authorization", Authorization);

            connection.setRequestMethod("GET");

            int responseCode = connection.getResponseCode();
            if (responseCode == 200) { // 响应成功，获取响应数据
                BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));

                String tempString;
                while ((tempString = reader.readLine()) != null) {
                    responseData += tempString;
                }
                reader.close();
            }

            connection.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return responseData;
    }
}
